package com.common.myspring.util;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * @title: BaseUtil
 * @Author xu-xiang
 * @Date: 2023/8/26 14:49
 * @description: 基础攻击类
 */
@Slf4j
public class BaseUtil {

    /**
     * 根据基础路径加载路径下所有的class文件
     * @param basePath 基础路径
     * @return
     */
    public static Set<Class<?>> getClassSetWithPath(String basePath) {
        if (basePath == null || basePath.isEmpty()) {
            return Collections.emptySet();
        }

        ClassLoader classLoader = BaseUtil.class.getClassLoader();
        URL resource = classLoader.getResource(basePath.replace(".", "/"));
        if (resource == null) {
            // TODO 抛出RuntimeException的子类: 具体异常类
            throw new RuntimeException("path: " + basePath + " error");
        }

        File packageDirectory = new File(resource.getPath());
        Set<Class<?>> classes = new HashSet<>();
        try {
            findClasses(packageDirectory, basePath, classLoader, classes);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }

        return classes;
    }

    /**
     * 循环遍历路径下,所有的子文件夹中的class
     * @param directory 基本文件夹
     * @param packageName 基础包名
     * @param classLoader 类加载器
     * @param classes 返回class集合
     * @throws ClassNotFoundException
     */
    private static void findClasses(
            File directory,
            String packageName,
            ClassLoader classLoader,
            Set<Class<?>> classes
    ) throws ClassNotFoundException {
        File[] files = directory.listFiles();

        if (files == null) {
            return;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                findClasses(file, packageName + "." + file.getName(), classLoader, classes);
            } else if (file.getName().endsWith(".class")) {
                // 获取class路径 eg: com.xx.YY
                String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                Class<?> clazz = Class.forName(className, false, classLoader);
                classes.add(clazz);
            }
        }
    }
}
